#ifndef __RING_QUEUE_HPP__
#define __RING_QUEUE_HPP__

#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>

template <typename T>
class RingQueue
{
private:
  int _cap;                   // 环形队列的容量上限
  std::vector<T> _ring_queue; // vector模拟环形队列

  // 2. 生产和消费的位置（下标）
  int _productor_step;
  int _consumer_step;

  // 3. 定义信号量
  sem_t _room_sem; // 空间资源
  sem_t _data_sem; // 数据资源

  // 4.定义锁，维护多生产多消费之间的互斥关系
  pthread_mutex_t _productor_mutex;
  pthread_mutex_t _consumer_mutex;

private:
  void
  P(sem_t &sem)
  {
    sem_wait(&sem);
  }
  void V(sem_t &sem)
  {
    sem_post(&sem);
  }
  void Lock(pthread_mutex_t &mutex)
  {
    pthread_mutex_lock(&mutex);
  }
  void Unlock(pthread_mutex_t &mutex)
  {
    pthread_mutex_unlock(&mutex);
  }

public:
  RingQueue(int cap) : _cap(cap), _ring_queue(cap), _productor_step(0), _consumer_step(0)
  {
    sem_init(&_room_sem, 0, _cap);
    sem_init(&_data_sem, 0, 0);
    pthread_mutex_init(&_productor_mutex, nullptr);
    pthread_mutex_init(&_consumer_mutex, nullptr);
  }
  // 生产
  void Enqueue(const T &in)
  {
    P(_room_sem);
    // 执行到这，一定有空间
    Lock(_productor_mutex);
    _ring_queue[_productor_step++] = in;
    _productor_step %= _cap;
    Unlock(_productor_mutex);
    V(_data_sem);
  }
  void Pop(T *out)
  {
    P(_data_sem);
    Lock(_consumer_mutex);
    *out = _ring_queue[_consumer_step++];
    _consumer_step %= _cap;
    Unlock(_consumer_mutex);
    V(_room_sem);
  }

  ~RingQueue()
  {
    sem_destroy(&_room_sem);
    sem_destroy(&_data_sem);
    pthread_mutex_destroy(&_productor_mutex);
    pthread_mutex_destroy(&_consumer_mutex);
  }
};

#endif